package com.demo.webflux.simple3;

import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.demo.webflux.domain.Book;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@RestController
public class BookController {

	private static Logger logger = LoggerFactory.getLogger(BookController.class);
	@Autowired
	private ReactiveSpringDataMongoBookRepository rxBookRepository;
	@Autowired
	private ReactiveMongoOperations mongoOperations; // ReactiveMongoTemplate实现了该接口，配置了mongodb数据源后，其出现在spring上下文里
	@Autowired
	private BookService bookService;

	private Flux<Book> books = Flux.just(new Book("java编程思想", new ArrayList<String>(){{add("zhangsan");}}, 2010), new Book("spring响应式编程", new ArrayList<String>(){{add("lisi");}}, 2019));

	// 先初始化数据
	@GetMapping("/save")
	public void save(){
		rxBookRepository.saveAll(books)
			.then()
			.doOnNext(ignore -> logger.info("book saved in db"))
			.subscribe();
	}

	// 通过title获取图书，然后更新publishYear，再保存
	@GetMapping("/update")
	public Mono<Boolean> updateBookYearByTitle() {
		Instant start = Instant.now();
		// 模拟远程获取title，假设1s
		Mono<String> title = Mono.delay(Duration.ofSeconds(1))
								.thenReturn("java编程思想")
								.doOnSubscribe(s -> logger.info("subscribed for title"))
								.doOnNext(t -> logger.info("book title resoved: {}", t));
		// 模拟获取publishYear，假设2s
		Mono<Integer> publishYear = Mono.delay(Duration.ofSeconds(2))
								.thenReturn(2017)
								.doOnSubscribe(s -> logger.info("subscribed for publishing year"))
								.doOnNext(t -> logger.info("now publishing year resoved: {}", t));

		return bookService.updateBookYearByTitle3(title, publishYear)
					.doOnSubscribe(b -> logger.info("publishing year updated for book: {}", b))
					.hasElement()
					.doOnSuccess(status -> logger.info("update finish {}, took: {}", status ? "successfully" : "unsuccessfully", Duration.between(start, Instant.now())));
	}

	@GetMapping("/title")
	public Mono<Book> findByTitle(){
		Query query = Query.query(new Criteria("title").is("java编程思想"));
		return mongoOperations.findOne(query, Book.class, "book");
	}

}
